/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id$ PersistenceServicesBean.java
 * Universidad de los Andes (Bogotá - Colombia)
 * Departamento de Ingeniería de Sistemas y Computación
 * Licenciado bajo el esquema Academic Free License version 2.1
 *
 * Ejercicio: Muebles los Alpes
 * Autor: Camilo Alvarez
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
package com.losalpes.catalogo.servicios;

import com.losalpes.catalogo.entities.Mueble;
import com.losalpes.catalogo.entities.RegistroVenta;
import com.losalpes.catalogo.entities.Usuario;
import com.losalpes.catalogo.entities.Vendedor;
import com.losalpes.catalogo.excepciones.InvalidOperationException;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * Implementación de los servicios de persistencia que se le prestan al sistema.
 * @author Camilo Alvarez
 */
@Stateless
public class PersistenceServicesBean implements IPersistenceServices,IPersistenceServicesRemote {

    @PersistenceContext
    EntityManager em;

    public PersistenceServicesBean() {
    }

    // -----------------------------------------------
    // Métodos
    // -----------------------------------------------
    /**
     * Permite crear un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere crear.
     */
    public void create(Object obj)throws InvalidOperationException{
        if (obj instanceof Vendedor) {
            Vendedor v = (Vendedor) obj;
            if(em.find(Vendedor.class, v.getIdentificacion()) == null ) {
                em.persist(v);
            }
        } else if (obj instanceof Mueble) {
            Mueble m = (Mueble) obj;
            em.persist(m);
        }
        else if (obj instanceof Usuario){
            Usuario usuario = (Usuario) obj;

            if(em.find(Usuario.class, usuario.getDocumento()) == null ) {
                em.persist(usuario);
            }
        }
        else if (obj instanceof RegistroVenta) {
            RegistroVenta rv = (RegistroVenta)obj;
            if(em.find(RegistroVenta.class, rv.getRegistroVentaPK()) == null ) {
                em.persist(rv);
            }
        }
    }

    /**
     * Permite modificar un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere modificar.
     */
    public void update(Object obj) {
        if (obj instanceof Vendedor) {
            updateSeller((Vendedor)obj);
        }
        else if (obj instanceof Mueble) {
            updateProduct((Mueble)obj);
        }
        else if (obj instanceof Usuario) {
            updateUser((Usuario)obj);
        }
    }

    public void updateUser(Usuario usr) {
        Usuario usuario = em.find(Usuario.class, usr.getDocumento());
        usuario.setDocumento(usr.getDocumento());
        usuario.setDireccion(usr.getDireccion());
        usuario.setCiudadResidencia(usr.getCiudadResidencia());
        usuario.setDepartamento(usr.getDepartamento());
        usuario.setEmail(usr.getEmail());
        usuario.setNombreCompleto(usr.getNombreCompleto());
        usuario.setPais(usr.getPais());
        usuario.setProfesion(usr.getProfesion());
        usuario.setPwd(usr.getPwd());
        usuario.setTelefonoCelular(usr.getTelefonoCelular());
        usuario.setTelefonoResidencia(usr.getTelefonoResidencia());
        usuario.setTipoDocumento(usr.getTipoDocumento());
        usuario.setUsuario(usr.getUsuario());
        em.merge(usuario);
    }

    public void updateSeller(Vendedor vend) {
        Vendedor vendedor = em.find(Vendedor.class, vend.getIdentificacion());
        vendedor.setApellidos(vend.getApellidos());
        vendedor.setComisionVentas(vend.getComisionVentas());
        vendedor.setExperiencia(vend.getExperiencia());
        vendedor.setFoto(vend.getFoto());
        vendedor.setIdentificacion(vend.getIdentificacion());
        vendedor.setNombres(vend.getNombres());
        vendedor.setPerfil(vend.getPerfil());
        vendedor.setSalario(vend.getSalario());
        em.merge(vendedor);
    }

     public void updateProduct(Mueble product) {
        Mueble mueble = em.find(Mueble.class, product.getReferencia());
        mueble.setAlto(product.getAlto());
        mueble.setAncho(product.getAlto());
        mueble.setColor(product.getColor());
        mueble.setDescripcion(product.getDescripcion());
        mueble.setMaterial(product.getMaterial());
        mueble.setNombre(product.getNombre());
        mueble.setPeso(product.getPeso());
        mueble.setProfundidad(product.getProfundidad());
        mueble.setReferencia(product.getReferencia());
        mueble.setTipo(product.getTipo());
        em.merge(mueble);
    }
    /**
     * Permite borrar un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere borrar.
     */
    public void delete(Object obj)throws InvalidOperationException{
        if (obj instanceof Vendedor) {
            Vendedor vendedorABorrar = (Vendedor) obj;
            if (vendedorABorrar != null && vendedorABorrar.getIdentificacion() != null) {
                vendedorABorrar = em.find(Vendedor.class, vendedorABorrar.getIdentificacion());
                em.remove(vendedorABorrar);
            }
            
        }
        else if (obj instanceof Mueble) {
            Mueble muebleABorrar = (Mueble) obj;
            if (muebleABorrar != null && muebleABorrar.getReferencia() != null) {
                muebleABorrar = em.find(Mueble.class, muebleABorrar.getReferencia());
                em.remove(muebleABorrar);
            }
        }
        else if (obj instanceof Usuario){
            Usuario usuarioABorrar = (Usuario) obj;
            if (usuarioABorrar != null && usuarioABorrar.getUsuario() != null) {
                StringBuilder jpql = new StringBuilder("RegistroVenta.findByUser");
                Query query = em.createNamedQuery(jpql.toString()).setParameter("documento", usuarioABorrar.getDocumento());
                if (!query.getResultList().isEmpty()) {
                    System.out.print("no borrado");
                    throw new InvalidOperationException("El usuario ha realizado compras y por lo tanto no puede ser eliminado del sistema.");
                }
                else {
                    usuarioABorrar = (Usuario)em.find(Usuario.class, usuarioABorrar.getDocumento());
                    em.remove(usuarioABorrar);
                    System.out.print("borrado");
                    
                }
            }
        }
    }

    /**
     * Retorna la lista de todos los elementos de una clase dada que se encuentran en el sistema.
     * @param c. Clase cuyos objetos quieren encontrarse en el sistema.
     * @return list. Listado de todos los objetos de una clase dada que se encuentran en el sistema.
     */
    public List findAll(Class c) {
        StringBuilder jpql = null;
        List rst = null;
        if (c.equals(Mueble.class)) {
            jpql = new StringBuilder("Mueble.findAll");
        }
        else if (c.equals(Vendedor.class)) {
            jpql = new StringBuilder("Vendedor.findAll");
        }
        else if (c.equals(Usuario.class)) {
            jpql = new StringBuilder("Usuario.findAll");
        }
        else if (c.equals(RegistroVenta.class)) {
            jpql = new StringBuilder("RegistroVenta.findAll");
        }
        else {
            return null;
        }
        Query query = em.createNamedQuery(jpql.toString());
        rst = query.getResultList();
        return rst;
    }

    /**
     * Retorna la instancia de una entidad dado un identificador y la clase de la entidadi.
     * @param c. Clase de la instancia que se quiere buscar.
     * @param id. Identificador unico del objeto.
     * @return obj. Resultado de la consulta.
     */
    public Object findById(Class c, Object id) {
        if (c.equals(Vendedor.class)) {
            for (Object v : findAll(c)) {
                Vendedor ven = (Vendedor) v;
                if (ven.getIdentificacion().equals(id)) {
                    return ven;
                }
            }
        }
        else if (c.equals(Mueble.class)) {
            for (Object v : findAll(c)) {
                Mueble mue = (Mueble) v;
                if (mue.getReferencia().compareTo(new Long(String.valueOf(id))) == 0)  {
                    return mue;
                }
            }
        }
        else if (c.equals(Usuario.class)) {
            for (Object v : findAll(c)) {
                Usuario mue = (Usuario) v;
                if (mue.getDocumento().equals(id)) {
                    return mue;
                }
            }
        }
        return null;
    }
}